#include "pch.h"
#include "LightEffect.h"

namespace mini
{
	CLightEffect::CLightEffect()
	{
		mOrder = Effect_Light;
		mPointLightInfo.resize(4);
	}

	CLightEffect::~CLightEffect()
	{
	}

	void CLightEffect::commitToGpu(DeviceContext* pDeviceContext)
	{
		int nRang = mPointLights.size() > NUM_LIGHTS ? NUM_LIGHTS : mPointLights.size();
		if (nRang > 0)
		{
			auto item = mPointLights.begin();
			for (int i = 0; i < nRang; ++i)
			{
				mPointLightInfo[i].lightPosition = (*item)->getPosition();
				mPointLightInfo[i].ambientColor = (*item)->getAmbientColor();
				mPointLightInfo[i].diffuseColor = (*item)->getDiffuseColor();
				mPointLightInfo[i].specularColor = (*item)->getSpecularColor();
				++item;
			}
			mpShader->updateVSConstBuffer(10, &mPointLightInfo[0], 0);
			mpShader->updatePSConstBuffer("LightPositionBuffer", &mPointLightInfo[0], 0);
			mpShader->use(pDeviceContext, 0);
			mpShader->commitToGpu(pDeviceContext);
		}

		if( nullptr != mpDirectionLight)
		{
			mDirectionLightInfo.ambientColor = mpDirectionLight->getAmbientColor();
			mDirectionLightInfo.diffuseColor = mpDirectionLight->getDiffuseColor();
			mDirectionLightInfo.specularColor = mpDirectionLight->getSpecularColor();
			mDirectionLightInfo.LightDirection = mpDirectionLight->getDirection();

			mpShader->updateVSConstBuffer(mpDirectionLight->getRegister(), &mDirectionLightInfo, mpDirectionLight->getPackoffset());
			mpShader->updatePSConstBuffer(mpDirectionLight->getName(), &mDirectionLightInfo, mpDirectionLight->getPackoffset());
			mpShader->use(pDeviceContext, 0);
			mpShader->commitToGpu(pDeviceContext);
		}

	}

	void CLightEffect::addActor(CActor* pActor)
	{
		auto pLight = dynamic_cast<CLightActor*>(pActor);
		if (nullptr != pLight)
		{
			if (pLight->getLightType() == Direction)
			{
				mpDirectionLight = dynamic_cast<CLightActor*>(pLight);
			}
			else 
			{
				mPointLights.push_back(dynamic_cast<CLightActor*>(pLight));
			}
		}
	}

	bool CLightEffect::init(CDevice* pDevice)
	{
		mpShader = new CShader();
		mpShader->setDevice(pDevice);
		if (mpShader->createVextexShader("resource/Shader/lightEffect.vs", "vsMain", "vs_5_0"))
		{
			if (mpShader->addVSParam("", sizeof(PointLightInfo) * NUM_LIGHTS, 10, 0))
			{
				if (mpShader->createPixelShader("resource/Shader/lightEffect.ps", "psMain", "ps_5_0"))
				{
					return mpShader->addPSParam("LightPositionBuffer", sizeof(PointLightInfo) * NUM_LIGHTS, 10, 0) &&
						   mpShader->addPSParam("Sun", sizeof(DirectionLightInfo), 0, 0);
				}
			}
		}
		return false;
	}

}